#include <Precomp.h>
#include "defs.h"
#include "GameWorld.h"
#include "GameHud.h"                
#include "Player.h"
#include "ClientListener.h"
#include "ServerConnection.h"
#include "AVUITextBlock.h"
#include "AVUIProgressBar.h"
#include "AVUIButton.h"

using namespace AVUI;


CGameHud::CGameHud(CGameWorld* pGameWorld, FrameworkElement* pRoot) : m_pGameWorld(pGameWorld), m_pRoot(pRoot), m_dwTime(0),
                                                               m_dwCachedFlags(0)

{
    m_pEventSubscription = pGameWorld->SubscribeEvents( CGameWorld::EventSubscriber(&CGameHud::OnGameWorldEvent, this));


    ((Button*)pRoot->FindName(object_allocate<String>(L"Refit")))->add_Click(RoutedEventHandler::Create(this, &CGameHud::OnRefit));

    m_pOrbitPanel = (FrameworkElement*) pRoot->FindName(object_allocate<String>(L"OrbitPanel"));
    m_pOrbitPanel->set_Visibility(Visibility::Collapsed);

    m_pRefitPanel = (FrameworkElement*) pRoot->FindName(object_allocate<String>(L"RefitPanel"));
    m_pRefitPanel->set_Visibility(Visibility::Collapsed);
}

void CGameHud::OnGameWorldEvent(CGameWorldEvent* pGameWorldEvent)
{
    if(pGameWorldEvent->GetEventID() != eGameWorldEventID_PlayerIsAlive)
    {
        return;
    }

    UpdateSpeed();
    UpdateArmies();
    UpdateKills();
    UpdateFuel();
    UpdateShield();
    UpdateDamage();
    UpdateEngineTemp();
    UpdateWeaponTemp();
    UpdateFlags();
}

CGameHud::~CGameHud()
{
    m_pGameWorld->UnsubscribeEvents(m_pEventSubscription);
}

void CGameHud::UpdateWindowTextValue(const char* szWindowName, const char* szFmt, ...)
{
    TextBlock* pTextBlock = object_cast<TextBlock>(m_pRoot->FindName(object_allocate<String>(szWindowName)));

    if(pTextBlock == NULL)
    {
        return;
    }

    char szBuf[256];
    va_list va;
    va_start(va, szFmt);

    vsnprintf_s(szBuf, sizeof(szBuf) - 1, _TRUNCATE, szFmt, va);
    szBuf[sizeof(szBuf) - 1] = '\0';
    
    pTextBlock->set_Text(object_allocate<String>(szBuf));

}

void CGameHud::UpdateProgressBarValue(const char* szWindowName, float flProgress)
{
    ProgressBar* pProgressBar = object_cast<ProgressBar>(m_pRoot->FindName(object_allocate<String>(szWindowName)));

    if(pProgressBar == NULL)
    {
        return;
    }

    pProgressBar->set_Value(flProgress);
}

void CGameHud::UpdateSpeed()
{
    DWORD dwSpeed = m_pGameWorld->GetPlayerForLocalPlayer()->GetSpeed();
    DWORD dwMaxSpeed = 0;

    if(m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData() != NULL)
    {
        dwMaxSpeed = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxSpeed();
    }

    UpdateWindowTextValue("WarpValue", "%2d/%2d", dwSpeed, dwMaxSpeed);

    m_dwCachedSpeed = dwSpeed;
}

void CGameHud::UpdateArmies()
{
    DWORD dwArmies = m_pGameWorld->GetLocalPlayer()->GetArmies();
    DWORD dwMaxArmies = 0;

    if(m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData() != NULL)
    {
        dwMaxArmies = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxArmies();
    }

    UpdateWindowTextValue("ArmiesValue", "%2d/%2d", dwArmies, dwMaxArmies);

    m_dwCachedArmies = dwArmies;
}

void CGameHud::UpdateKills()
{
    float flKills = m_pGameWorld->GetPlayerForLocalPlayer()->GetKills();

    UpdateWindowTextValue("KillsValue", "%.2f", flKills);

    m_flCachedKills = flKills;
}

void CGameHud::UpdateFuel()
{
    DWORD dwFuel = m_pGameWorld->GetLocalPlayer()->GetFuel();
    DWORD dwMaxFuel = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxFuel();

    UpdateProgressBarValue("FuelValue", (1.0f * dwFuel) / dwMaxFuel);
    UpdateWindowTextValue("FuelValueText", "%d/%d", dwFuel, dwMaxFuel);

    m_dwCachedFuel = dwFuel;
}

void CGameHud::UpdateShield()
{
    DWORD dwShield = m_pGameWorld->GetLocalPlayer()->GetShield();
    DWORD dwMaxShield = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxShield();

    UpdateProgressBarValue("ShieldValue", (1.0f * dwShield) / dwMaxShield);
    UpdateWindowTextValue("ShieldValueText", "%d/%d", dwShield, dwMaxShield);

    m_dwCachedShield = dwShield;
}

void CGameHud::UpdateDamage()
{
    DWORD dwDamage = m_pGameWorld->GetLocalPlayer()->GetDamage();
    DWORD dwMaxDamage = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxDamage();

    UpdateProgressBarValue("DamageValue", (1.0f * dwDamage) / dwMaxDamage);
    UpdateWindowTextValue("DamageValueText", "%d/%d", dwDamage, dwMaxDamage);

    m_dwCachedDamage = dwDamage;
}

void CGameHud::UpdateEngineTemp()
{
    DWORD dwEngineTemp = m_pGameWorld->GetLocalPlayer()->GetEngineTemp();
    DWORD dwMaxEngineTemp = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxEngineTemp();

    UpdateProgressBarValue("ETempValue", (1.0f * dwEngineTemp) / dwMaxEngineTemp);
    UpdateWindowTextValue("ETempValueText", "%d/%d", dwEngineTemp, dwMaxEngineTemp);

    m_dwCachedEngineTemp = dwEngineTemp;
}

void CGameHud::UpdateWeaponTemp()
{
    DWORD dwWeaponTemp = m_pGameWorld->GetLocalPlayer()->GetWeaponTemp();
    DWORD dwMaxWeaponTemp = m_pGameWorld->GetPlayerForLocalPlayer()->GetShipData()->GetMaxWeaponTemp();

    UpdateProgressBarValue("WTempValue", (1.0f * dwWeaponTemp) / dwMaxWeaponTemp);
    UpdateWindowTextValue("WTempValueText", "%d/%d", dwWeaponTemp, dwMaxWeaponTemp);

    m_dwCachedWeaponTemp = dwWeaponTemp;
}

void CGameHud::UpdateFlags()
{
    CGamePlayer* pPlayer = m_pGameWorld->GetPlayerForLocalPlayer();
    DWORD dwCachedFlags = pPlayer->GetFlags();

    if(dwCachedFlags & ePlayerFlag_Orbit)
    {
        m_pOrbitPanel->set_Visibility(Visibility::Visible);

        CPlanet* pPlanet = m_pGameWorld->GetPlanetByLocation(pPlayer->GetXLocation(), pPlayer->GetYLocation(), 1.5f);

        if(pPlanet != NULL && (pPlanet->GetFlags() & ePlanetFlag_Home) && pPlanet->GetTeamOwner() == pPlayer->GetTeamID())
        {
            m_pRefitPanel->set_Visibility(Visibility::Visible);
        }
    }
    else if(dwCachedFlags & ePlayerFlag_DockStarbase)
    {
        m_pRefitPanel->set_Visibility(Visibility::Visible);
    }
    else
    {
        m_pOrbitPanel->set_Visibility(Visibility::Collapsed);
        m_pRefitPanel->set_Visibility(Visibility::Collapsed);
    }

    m_dwCachedFlags = dwCachedFlags;
}

void CGameHud::UpdateTime(DWORD dwTimeIncrement)
{
    DWORD dwTimeInSec = m_dwTime / 1000;

    m_dwTime += dwTimeIncrement;

    DWORD dwNewTimeInSec = m_dwTime / 1000;

    if(dwTimeInSec != dwNewTimeInSec)
    {
        DWORD dwSeconds = dwNewTimeInSec % 60;
        DWORD dwMinutes = dwNewTimeInSec / 60;

        UpdateWindowTextValue("TimeValue", "%02d:%02d:%02d", dwMinutes / 60, dwMinutes % 60, dwSeconds);
    }
}



void CGameHud::FrameUpdate()
{
    UpdateTime((DWORD) (m_pGameWorld->GetListener()->GetTimeSinceLastFrameAsFloat() * 1000.0f));


    CGamePlayer* pPlayer = m_pGameWorld->GetPlayerForLocalPlayer();
    CLocalPlayer* pLocalPlayer = m_pGameWorld->GetLocalPlayer();

    if(pPlayer == NULL)
    {
        return;
    }
    if(pPlayer->GetSpeed() != m_dwCachedSpeed)
    {
        UpdateSpeed();
    }
    if(pLocalPlayer->GetArmies() != m_dwCachedArmies)
    {
        UpdateArmies();
    }
    if(pPlayer->GetKills() != m_flCachedKills)
    {
        UpdateKills();
    }
    if(pLocalPlayer->GetFuel() != m_dwCachedFuel)
    {
        UpdateFuel();
    }
    if(pLocalPlayer->GetShield() != m_dwCachedShield)
    {
        UpdateShield();
    }
    if(pLocalPlayer->GetDamage() != m_dwCachedDamage)
    {
        UpdateDamage();
    }
    if(pLocalPlayer->GetEngineTemp() != m_dwCachedEngineTemp)
    {
        UpdateEngineTemp();
    }
    if(pLocalPlayer->GetWeaponTemp() != m_dwCachedWeaponTemp)
    {
        UpdateWeaponTemp();
    }
    if(pPlayer->GetFlags() != m_dwCachedFlags)
    {
        UpdateFlags();
    }
}

void CGameHud::OnRefit(AVUI::Object*, AVUI::RoutedEventArgs*) { OnRefit(eShipType_Scout); }

void CGameHud::OnRefit(EShipType eShipType)
{
    struct refit_cpacket packet;

    packet.type = (char) EClientPacketType_Refit;
    packet.ship = (char) eShipType;

    m_pGameWorld->GetListener()->GetServerConnection()->SendPacket((packet_base*) &packet);

}

